#
# Copyright (c) 2023 supercell
#
# SPDX-License-Identifier: BSD-3-Clause
#

module Luce
  # Matches code blocks containing a subset of CSS color syntax
  class ColorSwatchSyntax < InlineSyntax
    # This pattern matches:
    # * GitHub Flavored Markup supports fewer of these options, GitLab Flavored
    #   Markup supports all of these. Presumably GitHub will be more complete at
    #   some point.
    # * CSS style '#' prefixed color hex codes in 3,4,6 or 8 digits in length.
    # * CSS style RGB()/RgbA()/Hsl()/HSLA() style color declarations, of any
    #   capitalization.
    # EXAMPLES:
    # * `#f00`
    # * `#BA`        (2 digit hex, regex will not match)
    # * `#F00a`
    # * `#F0BAD`     (5 digit hex, regex will not match)
    # * `#FF0000`
    # * `#F000BAD`   (7 digit hex, regex will not match)
    # * `#FF0000aA`    (GitHub supports only this style)
    # * `RGB(0,255,0)`
    # * `rgb(0,255,0)`
    # * `RGB(0%,100%,0%)`
    # * `rgb(0%,100%,0%)`
    # * `RGBA(0,255,0,0.3)`
    # * `rgba(0,255,0,0.3)`
    # * `HSL(540,70%,50%)`
    # * `hsl(540,70%,50%)`
    # * `HSLA(540,70%,50%,0.3)`
    # * `Hsla(540,70%,50%,0.3)`
    @@_pattern : String = %q{`((#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8}))|} +
      %q{([Rr][Gg][Bb][Aa]?\((\d+[%]?),(\d+[%]?),(\d+[%]?),?(\d+\.?\d+[%]?)?\))|} +
      %q{([Hh][Ss][Ll][Aa]?\((\d+[%]?),(\d+[%]?),(\d+[%]?),?(\d+\.?\d+[%]?)?\)))`}

    def initialize
      super(@@_pattern)
    end

    def matches?(parser : InlineParser, start_match_pos : Int32? = nil) : Bool
      if parser.pos > 0 && parser.char_at(parser.pos - 1) == Charcode::BACKQUOTE
        # Not really a match! We can't just sneak past one backtick to try the
        # next character. An example of this situation would be:
        #
        #     before ``` and `` after.
        #             ^--parser.pos
        return false
      end

      match = pattern.match(parser.source, parser.pos)
      return false if match.nil? || match.begin != parser.pos
      parser.write_text
      parser.consume(match[0].size) if on_match(parser, match)
      true
    end

    def on_match(parser : InlineParser, match : Regex::MatchData) : Bool
      code = match[1].strip.gsub("\n", " ")

      code = Luce.escape_html(code) if parser.encode_html?

      span_element = Element.with_tag("span")
      span_element.attributes["style"] = "background-color:#{code};"

      code_element = Element.new("code", [Text.new(code), span_element])
      code_element.attributes["class"] = "gfm-color_chip"

      parser.add_node(code_element)
      true
    end
  end
end
